using System.Drawing;
using System.Windows.Forms;
using Firestarter.Test.Base;
using FireStarterModeller.BO;
using FireStarterModeller.Test.BO;
using FireStarterModeller.UI;
using FireStarterModeller.UI.Relationship;
using Habanero.Base;
using Habanero.BO;
using Habanero.Faces.Base;
using Habanero.Faces.Win;
using NUnit.Framework;
 
using DockStyle=System.Windows.Forms.DockStyle;

namespace FireStarterModeller.Test.UI.Relationships
{
    [TestFixture]
    public class TestDMRelationshipPanelInfoControl
    {
        [TestFixtureSetUp]
        public void SetupFixture()
        {
            UITestUtils.SetupFixture();
        }


        [SetUp]
        public virtual void SetupTest()
        {
            UITestUtils.SetupTest();
        }

        private static IControlFactory GetControlFactory()
        {
            return GlobalUIRegistry.ControlFactory;
        }

        private void AssertContainsGroupBoxControl(DMRelationshipPanelInfoControl relationshipPanelInfoControl)
        {
            bool foundGroupBox = (GetGroupBox(relationshipPanelInfoControl) != null);
            Assert.IsTrue(foundGroupBox, "The Group box should have been found in the Controls collection");
        }

        private IGroupBox GetGroupBox(DMRelationshipPanelInfoControl relationshipPanelInfoControl)
        {
            foreach (object control in relationshipPanelInfoControl.Controls)
            {
                if (control is IGroupBox)
                {
                    return (IGroupBox) control;
                }
            }
            return null;
        }

        [Test]
        public void Test_Construct()
        {
            //---------------Set up test pack-------------------
            IControlFactory controlFactory = GetControlFactory();
            //---------------Assert Precondition----------------
            //---------------Execute Test ----------------------
            DMRelationshipPanelInfoControl relationshipPanelInfoControl = new DMRelationshipPanelInfoControl(controlFactory);
            //---------------Test Result -----------------------
            Assert.AreSame(controlFactory, relationshipPanelInfoControl.ControlFactory);
        }

        [Test]
        public void Test_MainLayout()
        {
            //---------------Set up test pack-------------------
            //---------------Assert Precondition----------------
            //---------------Execute Test ----------------------
            DMRelationshipPanelInfoControl relationshipPanelInfoControl = new DMRelationshipPanelInfoControl(GetControlFactory());
            //---------------Test Result -----------------------
            Assert.AreEqual(1, relationshipPanelInfoControl.Controls.Count);
            AssertContainsGroupBoxControl(relationshipPanelInfoControl);
            IGroupBox grpBox = GetGroupBox(relationshipPanelInfoControl);
            Assert.AreEqual(1, grpBox.Controls.Count);
            IControlHabanero groupBoxPanel = grpBox.Controls[0];
            Assert.AreEqual(2, groupBoxPanel.Controls.Count);
            Assert.IsTrue(groupBoxPanel.Controls.Contains(relationshipPanelInfoControl.DetailPanelInfo.Panel));
            Assert.IsTrue(groupBoxPanel.Controls.Contains(relationshipPanelInfoControl.MoreDetailPanel));
            //IControlHabanero detailControl = groupBoxPanel.Controls[0];
            //IControlHabanero moreDetailControl = groupBoxPanel.Controls[1];
            //Assert.That(moreDetailControl.Top, Is.GreaterThanOrEqualTo(detailControl.Bottom));
        }

        [Test]
        public void Test_DetailPanelLayout()
        {
            //---------------Set up test pack-------------------
            //---------------Assert Precondition----------------
            //---------------Execute Test ----------------------
            DMRelationshipPanelInfoControl relationshipPanelInfoControl = new DMRelationshipPanelInfoControl(GetControlFactory());
            //---------------Test Result --------------------------
            IControlHabanero detailControl = relationshipPanelInfoControl.DetailPanelInfo.Panel;
            Assert.AreNotEqual(0, detailControl.Controls.Count, "The Detail panel should have controls");
            Assert.IsTrue(detailControl.Controls.Contains(relationshipPanelInfoControl.RelatedClassFieldInfo.ControlMapper.Control));
            Assert.IsTrue(detailControl.Controls.Contains(relationshipPanelInfoControl.RelationshipNameFieldInfo.ControlMapper.Control));
            Assert.IsTrue(detailControl.Controls.Contains(relationshipPanelInfoControl.RelationshipTypeFieldInfo.ControlMapper.Control));
            Assert.IsInstanceOf(typeof(IComboBox), relationshipPanelInfoControl.RelatedClassFieldInfo.ControlMapper.Control);
            Assert.IsInstanceOf(typeof(ITextBox), relationshipPanelInfoControl.RelationshipNameFieldInfo.ControlMapper.Control);
            Assert.IsInstanceOf(typeof(IComboBox), relationshipPanelInfoControl.RelationshipTypeFieldInfo.ControlMapper.Control);       
        }

        [Test]
        public void Test_MoreDetailPanelLayout()
        {
            //---------------Set up test pack-------------------
            //---------------Assert Precondition----------------
            //---------------Execute Test ----------------------
            DMRelationshipPanelInfoControl relationshipPanelInfoControl = new DMRelationshipPanelInfoControl(GetControlFactory());
            //---------------Test Result --------------------------
            IControlHabanero moreDetailControl = relationshipPanelInfoControl.MoreDetailPanel;
            Assert.IsFalse(moreDetailControl.Visible, "Should not be visible at first");
            Assert.AreEqual(1, moreDetailControl.Controls.Count, "Should have 1 control.");
            Assert.IsTrue(moreDetailControl.Controls.Contains(relationshipPanelInfoControl.MultipleDetailPanelInfo.Panel));
        }

        [Test]
        public void Test_BusinessObject_GetAndSet()
        {
            //---------------Set up test pack-------------------
            DMRelationshipPanelInfoControl dmRelationshipPanelInfoControl = new DMRelationshipPanelInfoControl(GetControlFactory());
            DMRelationship dmRelationship = new DMRelationship();
            //---------------Assert Precondition----------------
            //---------------Execute Test ----------------------
            dmRelationshipPanelInfoControl.BusinessObject = dmRelationship;
            //---------------Test Result -----------------------
            Assert.AreSame(dmRelationship, dmRelationshipPanelInfoControl.BusinessObject);
        }

        [Test]
        public void Test_BusinessObject_WhenSet_ShouldSetToInnerPanels()
        {
            //---------------Set up test pack-------------------
            DMRelationshipPanelInfoControl relationshipPanelInfoControl = new DMRelationshipPanelInfoControl(GetControlFactory());
            DMRelationship newBO = new DMRelationship();
            //---------------Assert Precondition----------------
            Assert.IsNull(relationshipPanelInfoControl.BusinessObject);
            Assert.AreSame(relationshipPanelInfoControl.BusinessObject, relationshipPanelInfoControl.DetailPanelInfo.BusinessObject);
            Assert.AreSame(relationshipPanelInfoControl.BusinessObject, relationshipPanelInfoControl.MultipleDetailPanelInfo.BusinessObject);
            //---------------Execute Test ----------------------
            relationshipPanelInfoControl.BusinessObject = newBO;
            //---------------Test Result -----------------------
            Assert.AreSame(newBO, relationshipPanelInfoControl.BusinessObject);
            Assert.AreSame(newBO, relationshipPanelInfoControl.DetailPanelInfo.BusinessObject);
            Assert.AreSame(newBO, relationshipPanelInfoControl.MultipleDetailPanelInfo.BusinessObject);
        }

        [Test]
        public void Test_DMRelationship_GetAndSet()
        {
            //---------------Set up test pack-------------------
            DMRelationshipPanelInfoControl dmRelationshipPanelInfoControl = new DMRelationshipPanelInfoControl(GetControlFactory());
            DMRelationship dmRelationship = new DMRelationship();
            //---------------Assert Precondition----------------
            //---------------Execute Test ----------------------
            dmRelationshipPanelInfoControl.DMRelationship = dmRelationship;
            //---------------Test Result -----------------------
            Assert.AreSame(dmRelationship, dmRelationshipPanelInfoControl.DMRelationship);
        }

        [Test]
        public void Test_DMRelationship_WhenSetToNull_ShouldUpdatePanels()
        {
            //---------------Set up test pack-------------------
            DMRelationshipPanelInfoControl dmRelationshipPanelInfoControl = new DMRelationshipPanelInfoControl(GetControlFactory());
            DMRelationship dmRelationship = new DMRelationship();
            dmRelationshipPanelInfoControl.DMRelationship = dmRelationship;
            //---------------Assert Precondition----------------
            Assert.AreSame(dmRelationship, dmRelationshipPanelInfoControl.DMRelationship);
            //---------------Execute Test ----------------------
            dmRelationshipPanelInfoControl.DMRelationship = null;
            //---------------Test Result -----------------------
            Assert.IsNull(dmRelationshipPanelInfoControl.DMRelationship);
            Assert.IsNull(dmRelationshipPanelInfoControl.BusinessObject);
            Assert.IsNull(dmRelationshipPanelInfoControl.DetailPanelInfo.BusinessObject);
            Assert.IsNull(dmRelationshipPanelInfoControl.MultipleDetailPanelInfo.BusinessObject);
        }

        [Test]
        public void Test_DMRelationship_IsSameAsBusinessObject()
        {
            //---------------Set up test pack-------------------
            DMRelationshipPanelInfoControl relationshipPanelInfoControl = new DMRelationshipPanelInfoControl(GetControlFactory());
            DMRelationship newBO = new DMRelationship();
            //---------------Assert Precondition----------------
            Assert.AreEqual(relationshipPanelInfoControl.DMRelationship, relationshipPanelInfoControl.BusinessObject);
            //---------------Execute Test ----------------------
            relationshipPanelInfoControl.DMRelationship = newBO;
            //---------------Test Result -----------------------
            Assert.AreSame(newBO, relationshipPanelInfoControl.DMRelationship);
            Assert.AreSame(newBO, relationshipPanelInfoControl.BusinessObject);
        }

        [Test]
        public void Test_BusinessObject_IsSameAsDMRelationship()
        {
            //---------------Set up test pack-------------------
            DMRelationshipPanelInfoControl relationshipPanelInfoControl = new DMRelationshipPanelInfoControl(GetControlFactory());
            DMRelationship newBO = new DMRelationship();
            //---------------Assert Precondition----------------
            Assert.AreEqual(relationshipPanelInfoControl.BusinessObject, relationshipPanelInfoControl.DMRelationship);
            //---------------Execute Test ----------------------
            relationshipPanelInfoControl.BusinessObject = newBO;
            //---------------Test Result -----------------------
            Assert.AreSame(newBO, relationshipPanelInfoControl.BusinessObject);
            Assert.AreSame(newBO, relationshipPanelInfoControl.DMRelationship);
        }

        [Test]
        public void Test_DMRelationship_WhenSet_ShouldSetUpRelatedClassControlMapperCollection()
        {
            //--------------- Set up test pack ------------------
            DMClass dmClass = TestUtilsShared.CreateUnsavedValidDMClass();
            DMSolution solution = dmClass.Assembly.Solution;
            DMClass dmClass2 = solution.DefaultAssembly.CreateClass(TestUtilsShared.GetRandomString());
            DMRelationship relationship = dmClass.OwnerRelationships.CreateBusinessObject();
            BusinessObjectCollection<DMClass> allClasses = solution.AllClasses;
            DMRelationshipPanelInfoControl dmRelationshipPanelInfoControl = new DMRelationshipPanelInfoControl(GetControlFactory());
            //--------------- Test Preconditions ----------------
            Assert.AreEqual(2, allClasses.Count);
            //--------------- Execute Test ----------------------
            dmRelationshipPanelInfoControl.DMRelationship = relationship;
            //--------------- Test Result -----------------------
            PanelInfo.FieldInfo fieldInfo = dmRelationshipPanelInfoControl.RelatedClassFieldInfo;
            Assert.IsNotNull(fieldInfo);
            Assert.IsInstanceOf(typeof(RelationshipComboBoxMapper), fieldInfo.ControlMapper);
            IBusinessObjectCollection objectCollection = ((RelationshipComboBoxMapper)fieldInfo.ControlMapper).BusinessObjectCollection;
            Assert.AreSame(allClasses, objectCollection);
            Assert.AreEqual(allClasses.Count + 1, ((IComboBox)fieldInfo.InputControl).Items.Count);
        }

        [Test]
        public void Test_DMRelationship_WhenSet_WhenCardinalityMultiple_ShouldShowMultipleProps()
        {
            //--------------- Set up test pack ------------------
            DMRelationshipPanelInfoControl dmRelationshipPanelInfoControl = new DMRelationshipPanelInfoControl(GetControlFactory());
            DMRelationship relationship = new DMRelationship {Cardinality = null};
            dmRelationshipPanelInfoControl.DMRelationship = relationship;
            DMRelationship multipleRelationship = new DMRelationship { Cardinality = Cardinality.Multiple };
            //--------------- Test Preconditions ----------------
            Assert.AreEqual(Cardinality.Multiple, multipleRelationship.Cardinality);
            AssertMoreDetailVisibility(false, dmRelationshipPanelInfoControl);
            //--------------- Execute Test ----------------------
            dmRelationshipPanelInfoControl.DMRelationship = multipleRelationship;
            //--------------- Test Result -----------------------
            AssertMoreDetailVisibility(true, dmRelationshipPanelInfoControl);
        }

        [Test]
        public void Test_DMRelationship_WhenSet_WhenCardinalitySingle_ShouldHideMultipleProps()
        {
            //--------------- Set up test pack ------------------
            DMRelationshipPanelInfoControl dmRelationshipPanelInfoControl = new DMRelationshipPanelInfoControl(GetControlFactory());
            DMRelationship multipleRelationship = new DMRelationship { Cardinality = Cardinality.Multiple };
            dmRelationshipPanelInfoControl.DMRelationship = multipleRelationship;
            DMRelationship singleRelationship = new DMRelationship { Cardinality = Cardinality.Single };
            //--------------- Test Preconditions ----------------
            Assert.AreEqual(Cardinality.Single, singleRelationship.Cardinality);
            AssertMoreDetailVisibility(true, dmRelationshipPanelInfoControl);
            //--------------- Execute Test ----------------------
            dmRelationshipPanelInfoControl.DMRelationship = singleRelationship;
            //--------------- Test Result -----------------------
            AssertMoreDetailVisibility(false, dmRelationshipPanelInfoControl);
        }

        [Test]
        public void Test_DMRelationship_WhenSet_WhenCardinalityNull_ShouldHideMultipleProps()
        {
            //--------------- Set up test pack ------------------
            DMRelationshipPanelInfoControl dmRelationshipPanelInfoControl = new DMRelationshipPanelInfoControl(GetControlFactory());
            DMRelationship multipleRelationship = new DMRelationship { Cardinality = Cardinality.Multiple };
            dmRelationshipPanelInfoControl.DMRelationship = multipleRelationship;
            DMRelationship relationship = new DMRelationship { Cardinality = null };
            //--------------- Test Preconditions ----------------
            Assert.IsNull(relationship.Cardinality);
            //Assert.AreEqual(Cardinality.Multiple, relationship.Cardinality);
            AssertMoreDetailVisibility(true, dmRelationshipPanelInfoControl);
            //--------------- Execute Test ----------------------
            dmRelationshipPanelInfoControl.DMRelationship = relationship;
            //--------------- Test Result -----------------------
            AssertMoreDetailVisibility(false, dmRelationshipPanelInfoControl);
        }

        [Test]
        public void Test_DMRelationship_WhenSetToNull_ShouldHideMultipleProps()
        {
            //--------------- Set up test pack ------------------
            DMRelationshipPanelInfoControl dmRelationshipPanelInfoControl = new DMRelationshipPanelInfoControl(GetControlFactory());
            DMRelationship multipleRelationship = new DMRelationship { Cardinality = Cardinality.Multiple };
            dmRelationshipPanelInfoControl.DMRelationship = multipleRelationship;
            //--------------- Test Preconditions ----------------
            AssertMoreDetailVisibility(true, dmRelationshipPanelInfoControl);
            //--------------- Execute Test ----------------------
            dmRelationshipPanelInfoControl.DMRelationship = null;
            //--------------- Test Result -----------------------
            AssertMoreDetailVisibility(false, dmRelationshipPanelInfoControl);
        }

        [Test]
        public void Test_DMRelationship_WhenCardinalityChangedToMultiple_ShouldShowMultipleProps()
        {
            //--------------- Set up test pack ------------------
            DMRelationshipPanelInfoControl dmRelationshipPanelInfoControl = new DMRelationshipPanelInfoControl(GetControlFactory());
            DMRelationship relationship = new DMRelationship { Cardinality = null };
            dmRelationshipPanelInfoControl.DMRelationship = relationship;
            //--------------- Test Preconditions ----------------
            Assert.IsNull(relationship.Cardinality);
            AssertMoreDetailVisibility(false, dmRelationshipPanelInfoControl);
            //--------------- Execute Test ----------------------
            relationship.Cardinality = Cardinality.Multiple;
            //--------------- Test Result -----------------------
            Assert.AreEqual(Cardinality.Multiple, relationship.Cardinality);
            AssertMoreDetailVisibility(true, dmRelationshipPanelInfoControl);
        }

        [Test]
        public void Test_DMRelationship_WhenCardinalityChangedToSingle_ShouldHideMultipleProps()
        {
            //--------------- Set up test pack ------------------
            DMRelationshipPanelInfoControl dmRelationshipPanelInfoControl = new DMRelationshipPanelInfoControl(GetControlFactory());
            DMRelationship relationship = new DMRelationship { Cardinality = Cardinality.Multiple };
            dmRelationshipPanelInfoControl.DMRelationship = relationship;
            //--------------- Test Preconditions ----------------
            Assert.AreEqual(Cardinality.Multiple, relationship.Cardinality);
            AssertMoreDetailVisibility(true, dmRelationshipPanelInfoControl);
            //--------------- Execute Test ----------------------
            relationship.Cardinality = Cardinality.Single;
            //--------------- Test Result -----------------------
            Assert.AreEqual(Cardinality.Single, relationship.Cardinality);
            AssertMoreDetailVisibility(false, dmRelationshipPanelInfoControl);
        }

        [Test]
        public void Test_DMRelationship_WhenCardinalityChangedToNull_ShouldHideMultipleProps()
        {
            //--------------- Set up test pack ------------------
            DMRelationshipPanelInfoControl dmRelationshipPanelInfoControl = new DMRelationshipPanelInfoControl(GetControlFactory());
            DMRelationship relationship = new DMRelationship { Cardinality = Cardinality.Multiple };
            dmRelationshipPanelInfoControl.DMRelationship = relationship;
            //--------------- Test Preconditions ----------------
            Assert.AreEqual(Cardinality.Multiple, relationship.Cardinality);
            AssertMoreDetailVisibility(true, dmRelationshipPanelInfoControl);
            //--------------- Execute Test ----------------------
            relationship.Cardinality = null;
            //--------------- Test Result -----------------------
            Assert.IsNull(relationship.Cardinality);
            AssertMoreDetailVisibility(false, dmRelationshipPanelInfoControl);
        }

        [Ignore("This test is incomplete. Need to check relationship name")]
        //TODO Mark 04 Sep 2009: Ignored Test - This test is incomplete. Need to check relationship name
        [Test]
        public void Test_WhenSelectRelatedClass_ThenSetsUpRelationshiopName()
        {
            //---------------Set up test pack-------------------
            TestUtilsDomain.WaitForGC();
            BORegistry.DataAccessor = new DataAccessorInMemory();
            DMClass dmClass = TestUtilsDMClass.CreateSavedDMClass("a11111111");
            DMRelationship relationship = dmClass.OwnerRelationships.CreateBusinessObject();
            DMClass otherClass = TestUtilsDMClass.CreateSavedDMClass(dmClass.Solution);
            otherClass.ClassNameBO = "a222222222";
            DMRelationshipPanelInfoControl relationshipPanelInfoControl = new DMRelationshipPanelInfoControl
                (GetControlFactory());
            relationshipPanelInfoControl.BusinessObject = relationship;
            IComboBox relatedClassComboBox = (IComboBox) relationshipPanelInfoControl.RelatedClassFieldInfo.InputControl;
            //---------------Assert Precondition----------------
            Assert.IsNotNull(relationshipPanelInfoControl.BusinessObject);
            Assert.IsNotNull(relationship.OwnerClass);
            Assert.IsNull(relationship.RelatedClass);
            Assert.AreEqual(3, relatedClassComboBox.Items.Count);
            Assert.AreEqual("", relatedClassComboBox.Items[0]);
            Assert.AreSame(dmClass, relatedClassComboBox.Items[1]);
            Assert.AreSame(otherClass, relatedClassComboBox.Items[2]);
            Assert.AreEqual(null, relatedClassComboBox.SelectedItem);
            //---------------Execute Test ----------------------
            relatedClassComboBox.SelectedIndex = 2;
            //---------------Test Result -----------------------
            Assert.AreSame(otherClass, relatedClassComboBox.SelectedItem);
        }

        //[Ignore("Changing how this works")]
        //[Test]
        //public void Test_DisplayErrors()
        //{
        //    //---------------Set up test pack-------------------
        //    DMRelationshipPanelInfoControl dmClassEditorControl = new DMRelationshipPanelInfoControl
        //        (GetControlFactory());
        //    DMClass newBO = new DMClass();
        //    dmClassEditorControl.BusinessObject = newBO;
        //    PanelInfo.FieldInfo fieldInfo = dmClassEditorControl.DetailPanelInfo.FieldInfos["ClassNameBO"];
        //    //---------------Assert Precondition----------------
        //    Assert.IsFalse(fieldInfo.ControlMapper.ErrorProvider.GetError(fieldInfo.InputControl).Length > 0);

        //    //---------------Execute Test ----------------------
        //    dmClassEditorControl.DisplayErrors();

        //    //---------------Test Result -----------------------
        //    Assert.IsTrue(fieldInfo.ControlMapper.ErrorProvider.GetError(fieldInfo.InputControl).Length > 0);
        //}

        //[Ignore("Changing how this works")]
        //[Test]
        //public void Test_ClearErrors()
        //{
        //    //---------------Set up test pack-------------------
        //    DMRelationshipPanelInfoControl dmClassEditorControl = new DMRelationshipPanelInfoControl
        //        (GetControlFactory());
        //    DMClass newBO = new DMClass();
        //    dmClassEditorControl.BusinessObject = newBO;
        //    PanelInfo.FieldInfo fieldInfo = dmClassEditorControl.DetailPanelInfo.FieldInfos["ClassNameBO"];
        //    dmClassEditorControl.DisplayErrors();

        //    //---------------Assert Precondition----------------
        //    Assert.IsTrue(fieldInfo.ControlMapper.ErrorProvider.GetError(fieldInfo.InputControl).Length > 0);

        //    //---------------Execute Test ----------------------
        //    dmClassEditorControl.ClearErrors();

        //    //---------------Test Result -----------------------
        //    Assert.IsFalse(fieldInfo.ControlMapper.ErrorProvider.GetError(fieldInfo.InputControl).Length > 0);
        //}

        [Test]
        [Ignore("This is for visual testing purposes")]
        public void Test_Visually()
        {
            //---------------Set up test pack-------------------
            TestUtilsDomain.WaitForGC();
            BORegistry.DataAccessor = new DataAccessorInMemory();
            DMClass dmClass = TestUtilsDMClass.CreateSavedDMClass("a11111111");
            DMRelationship relationship = dmClass.OwnerRelationships.CreateBusinessObject();
            DMClass otherClass = TestUtilsDMClass.CreateSavedDMClass("a11111111112");

            IControlFactory controlFactory = GetControlFactory();
            DMRelationshipPanelInfoControl relationshipPanelInfoControl = new DMRelationshipPanelInfoControl(controlFactory);
            relationshipPanelInfoControl.BusinessObject = relationship;
            //---------------Assert Precondition----------------
            //---------------Execute Test ----------------------
            TestUtilsUI.ShowInVisualTestingForm(controlFactory, relationshipPanelInfoControl, Habanero.Faces.Base.DockStyle.Top);
            //---------------Test Result -----------------------
        }

        private static void AssertMoreDetailVisibility(bool visible, DMRelationshipPanelInfoControl dmRelationshipPanelInfoControl)
        {
            IPanel moreDetailPanel = dmRelationshipPanelInfoControl.MoreDetailPanel;
            IPanel detailPanel = dmRelationshipPanelInfoControl.DetailPanelInfo.Panel;
            Assert.AreEqual(visible, moreDetailPanel.Visible);
            if (visible)
            {
                //Assert.That(dmRelationshipPanelInfoControl.Height, Is.GreaterThanOrEqualTo(detailPanel.Height + moreDetailPanel.Height));
            }
        }
    }
}